package com.mazong.serversecaa.security;

import com.mazong.serversecaa.IDbSecurityMapper;
import com.mazong.serversecaa.pojo.TbRolePermission;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.web.filter.CharacterEncodingFilter;

import java.util.List;

@Slf4j
@Configuration
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    MyAuthenticationProvider myAuthenticationProvider;

    @Autowired
    MyFilterInvocationSecurityMetadataSource myFilterInvocationSecurityMetadataSource;

    @Autowired
    MyAccessDecisionManager myAccessDecisionManager;

    @Autowired
    IDbSecurityMapper iDbSecurityMapper;

    /**
     * 用户账号
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        auth.inMemoryAuthentication()
//                .passwordEncoder(getPasswordEncoder())
//                .withUser("david")
//                .password(getPasswordEncoder().encode("123456"))
//                .authorities("USER");
        auth.authenticationProvider(myAuthenticationProvider);
    }

    /**
     * 用户权限
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        List<TbRolePermission> permissions = iDbSecurityMapper.getRolePermissons();
        for(TbRolePermission permission : permissions) {
            String url = permission.getUrl();
            String roleName = permission.getRoleName();

            http.authorizeRequests().antMatchers(url).hasAuthority(roleName);
        }

        http.authorizeRequests()
                .antMatchers("/login","/login-eror").permitAll()
                .antMatchers("/**")
                .authenticated();

        // 自定义登录页面
        http.formLogin().loginPage("/login").failureUrl("/login-error").defaultSuccessUrl("/index");

        // 定义访问被拒绝的自定义错误页面
        http.exceptionHandling().accessDeniedPage("/403");


        // 登出授权
        http.logout().logoutUrl("/logout").permitAll();

/*
        http.authorizeRequests()
                .antMatchers("/login", "/logout", "/login-error").permitAll()
                .antMatchers("/**").authenticated()
                .and()
                .formLogin().loginPage("/login").defaultSuccessUrl("/index").failureUrl("/login-error");

        http.authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O o) {
                        o.setSecurityMetadataSource(myFilterInvocationSecurityMetadataSource);
                        o.setAccessDecisionManager(myAccessDecisionManager);
                        return o;
                    }
                });
*/
/*
        // 登录
        http.formLogin().loginPage("/login").loginProcessingUrl("/login")
                .defaultSuccessUrl("/index")
                .failureUrl("/login-error");
        http.authorizeRequests()
                .antMatchers("/login").permitAll();

        // 解决非thymeleaf的form表单提交被拦截问题
        http.csrf().disable();

        http.authorizeRequests()
                .antMatchers("/login")
                .permitAll()
                .anyRequest()
                .authenticated();

        //session管理
        //session失效后跳转到登录页面
        http.sessionManagement().invalidSessionUrl("/login");

        //单用户登录，如果有一个登录了，同一个用户在其他地方登录将前一个剔除下线
        //http.sessionManagement().maximumSessions(1).expiredSessionStrategy(expiredSessionStrategy());

        //单用户登录，如果有一个登录了，同一个用户在其他地方不能登录
        http.sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true);

        //退出删除cookie
        http.logout()
                .permitAll()
                .logoutUrl("/logout")  //执行注销的url
                .invalidateHttpSession(true) // 指定是否在注销时让httpSession无效
                .deleteCookies("JESSIONID")  // 清除cookie
                .logoutSuccessUrl("/login"); // 注销成功后跳转的url
        super.configure(http);

        //解决中文乱码问题
        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        filter.setEncoding("UTF-8");
        filter.setForceEncoding(true);
        //http.addFilterBefore(filter,CsrfFilter.class);

        //http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class);
*/
/*
        http.authorizeRequests()
//                .antMatchers("/product/select").hasAuthority("USER")
//                .antMatchers("/product/insert").hasAuthority("USER")
//                .antMatchers("/product/update").hasAuthority("ADMIN")
//                .antMatchers("/product/delete").hasAuthority("ADMIN")
                .anyRequest().authenticated()
                .antMatchers("/login","/login-eror").permitAll()
                .antMatchers("/**")
                .authenticated()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O o) {
                        o.setSecurityMetadataSource(myFilterInvocationSecurityMetadataSource);
                        o.setAccessDecisionManager(myAccessDecisionManager);
                        return o;
                    }
                })
        .and()
        //.httpBasic();
                // 自定义登录页面
        .formLogin().loginPage("/login").failureUrl("/login-error").defaultSuccessUrl("/index")
        .and()
                // 定义访问被拒绝的自定义错误页面
        .exceptionHandling().accessDeniedPage("/403");
*/
    }

    // 定义密码加密算法
    private PasswordEncoder getPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
